Table form
Создание компонента
Компонент Table Form позволяет отображать выбранные значения в виде таблицы.
Созданные записи являются временными и хранятся в памяти браузера. Отправляются на сервер вместе с родительской формой.
Для отображения кнопки Создать и возможности вызова формы создания используется formKey*, который может быть вычислен в зависимости от настройки Типа данных на вкладке Данные:
Журнал - варианты создания вычисляются с помощью настройки ID журнала, либо на основе типа ассоциации, которая указана в атрибуте (при этом ID журнала заполнять не нужно). Есть возможность выбрать колонки для отображения в таблице.
Пользовательские - варианты создания вычисляются на основе типа ассоциации, которая указана в атрибуте. При этом требуется добавить вручную колонки для отображения в таблице (соответствуют названиям полей в форме создания).
Варианты создания определяются из указанного аттрибута на вкладке API, либо из настройки Пользовательские варианты создания на вкладке Данные. Настройки колонок берутся из первого по списку полученного варианта создания. Если нет ни одного доступного варианта создания, кнопка Создать будет скрыта.
Для каждой колонки можно задать настройки вручную. Для этого нужно отметить галочкой пункт Установить атрибуты вручную:
Таким образом можно установить заголовок колонки (может быть задан в двух локализация), тип данных и признак Выбор нескольких.
Предусмотрена возможность применения к колонке форматтера вручную. Опция Установить атрибуты вручную не влияет на настройку форматтера. Поле настройки форматтера принимает значение вида:
value = {
type: 'script',
config: {
fn: function(...params) {
const linkHtml = `<a href="${params[0].cell}">${params[0].cell}</a>`
return {
type: 'html',
config: {html: linkHtml}
}
}
}
};
Привязка к атрибуту родительского типа
Для корректной связи tableForm с родительской записью необходимо указать атрибут-ассоциацию на вкладке API в поле Свойство (Property Name), либо в блоке Свойства (Properties) задать ключ attribute со значением — именем атрибута на родительском типе.
Например, если на родительском типе определён атрибут:
- id: risks
type: ASSOC
config:
typeRef: emodel/type@project-risk-item
child: true
multiple: true
То в настройках tableForm:
key компонента =
risks(совпадает с id атрибута), илив блоке Properties указать
attribute=risks
Без этой привязки tableForm не сможет сохранить дочерние записи при отправке родительской формы.
Кнопки «Создать» и «Выбрать»
Компонент Table Form поддерживает два способа добавления записей:
Создать — открывает пустую форму создания новой записи. Запись создаётся с нуля как дочерний элемент родительской сущности. Варианты создания определяются из журнала, указанного в source.journal.journalId, или из типа ассоциации атрибута.
Выбрать — открывает журнал-справочник, из которого можно выбрать существующую запись. Выбранная запись используется как шаблон: она копируется (клонируется) в таблицу как новая дочерняя запись. Оригинал в справочнике не изменяется.
Кнопка «Выбрать» отображается только при установленном флаге Кнопка «Выбрать» и указанном selectJournalId (идентификатор журнала для выбора шаблонов).
Примечание
Журнал для кнопки «Создать» (source.journal.journalId) и журнал для кнопки «Выбрать» (selectJournalId) — это, как правило, разные журналы. Первый отображает дочерние элементы в таблице, второй — справочник шаблонов для копирования.
Выбор значения из справочника
Чтобы на форме отображалась кнопка «Выбрать» для копирования существующих объектов, установите флаг Кнопка «Выбрать»:
Укажите идентификатор журнала для выбора объектов. Если идентификатор не указан, будет использован журнал соответствующий типу первого варианта создания.
На форме нажмите кнопку «Выбрать».
Выберите необходимый объект для копирования. Выбираемое значение используется как шаблон для копируемого объекта.
Открывается форма редактирования объекта, если необходимо, то можно изменить значения.
Подтвердите выбор, объект будет скопирован в table form.
Структура типов для корректной работы копирования
Чтобы копирование из справочника работало правильно (записи создавались как дочерние элементы родительской сущности и не попадали в глобальный справочник), необходима двухуровневая иерархия типов:
data-list
└── <тип-справочник> ← справочник (шаблоны для выбора)
└── <тип-элемент> ← дочерний тип (создаётся при копировании)
Пример из CRM (продукты и услуги):
# Тип-справочник (глобальный каталог шаблонов)
id: product-and-services
parentRef: emodel/type@data-list
# Тип-элемент (дочерняя запись сделки/заказа)
id: product-and-services-item
parentRef: emodel/type@product-and-services
Конфигурация ассоциации на родительском типе (сделка/заказ):
- id: product-and-services
type: ASSOC
config:
typeRef: emodel/type@product-and-services-item # ← тип-элемент, не справочник
child: true
multiple: true
Конфигурация компонента Table Form на форме:
{
"key": "has-pas:product-and-services",
"type": "tableForm",
"source": {
"type": "journal",
"journal": {
"journalId": "product-and-services-item"
}
},
"enableSelectButton": true,
"selectJournalId": "product-and-services-template",
"properties": {
"attribute": "has-pas:product-and-services"
}
}
Где:
source.journal.journalId— журнал типа-элемента (для отображения строк в таблице)selectJournalId— журнал типа-справочника (для выбора шаблонов при нажатии кнопки «Выбрать»)properties.attribute— атрибут-ассоциация на родительском типе
Важно
Если тип-элемент наследуется напрямую от data-list, созданные записи будут попадать в глобальный справочник. Тип-элемент должен наследоваться от типа-справочника (или другого не-справочного типа), чтобы записи существовали только как дочерние элементы родительской сущности.
Наполнение данных в таблице
Использование Массив записей
Для этого можно использовать компонент Async Data (добавить ссылку) с типом данных Массив записей (Records Array).
В поле Массив записей (Records Array) указывается имя таблицы, заключенное в двойные фигурные скобки, в аттрибутах - поля этой таблицы и ключи, по которым они будут доступны.
Ручное заполнение
Table form ожидает, что value в нем будет массивом recordRef. Данные по рекордам будут подтянуты автоматически.
Таким образом, можем в async data получить какие-то данные, например, через recordsQuery, а в table form (вкладка Данные -> Вычисляемые значения) преобразовать их в массив recordRef и назначить в value:
const uncompletedIssues = _.get(data, 'uncompletedIssues.records') || [];
const issueIds = uncompletedIssues.map(issue => issue.id);
value = issueIds;
Как получить доступ к родительской форме?
Чтобы получить доступ к родительской форме из формы создания/редактирования записи, можно использовать объект instance.options.parentForm.
Например, если требуется установить значение по умолчанию полю дочерней формы, опираясь на значение из поля родительской формы, можно установить этому полю настройку Пользовательские значения по умолчанию:
if (instance.options.parentForm) {
value = instance.options.parentForm.getValue()['data']['someParentFormFieldName']
}
Отображение действий
Вкладка Отображение, настройка Элементы отображения позволяет задавать условия отображения действий.
Есть два варианта установки действий:
Использовать действия журнала — флаг на вкладке Отображение. При включении в строках таблицы отображаются действия, заданные в конфигурации журнала (секция
actionsв YAML журнала). Например, если в журнале указаныuiserv/action@editиuiserv/action@delete, в каждой строке таблицы будут доступны кнопки редактирования и удаления. Рекомендуется включать, когда источник данных — Журнал.Если источник не журнал или не нужны журнальные действия, и заполнено поле Действия компонентов, отобразятся доступные стандартные действия, описанные ниже.
Если установлен флаг Использовать действия журнала, то из поля Действия компонентов будет обработано только действие Создать.
Наименование действия |
Ключ |
По умолчанию |
disabled / режим просмотра |
|---|---|---|---|
Создать |
create |
true |
недоступно или скрыто |
Редактировать |
edit |
true |
недоступно |
Удалить |
delete |
true |
недоступно |
Просмотр |
view |
true |
|
Предпросмотр документа |
preview |
false |
|
Клонировать |
clone |
false |
Поле принимает javascript-выражение, в котором необходимо присвоить переменной value объект с необязательными свойствами create, view, preview, edit и delete (ключи в таблице выше).
Если какое-то из свойств не указано, то компонент сам будет решать, отображать элемент или скрывать, в зависимости от ситуации (*).
Если компонент Table Form в состоянии disabled или форма в режиме просмотра, элементы “редактировать“, “удалить“ в любом случае будут недоступны.
value = {
create: false,
view: false,
edit: false,
delete: true,
preview: true
}
Настройки элементов
Вкладка Отображение настройка Элементы отображения задает некоторые свойства действиям.
Копирование без подтверждения
Если флаг установлен, при выборе из справочника запись сразу копируется в таблицу без открытия формы редактирования. Если флаг снят, сначала открывается форма, в которой можно изменить значения перед добавлением.
Выбор строк в таблице и выполнение действий с выбранными строками
Для включения возможности выбора строки в таблице нужно отметить галочкой пункт Выбираемые строки на вкладке Данные.
Для получения списка выбранных строк в таблице у компонента предусмотрен метод getSelectedRows().
Например, чтобы выполнить какое-нибудь действие с выбранными строками в таблице при нажатии на кнопку, в компоненте Button выберем Действия: Custom и укажем Button Custom Logic:
const tableFormComponent = utils.getComponent(form.components, 'tableFormComponentKey');
if (!tableFormComponent) {
return;
}
const selectedRows = tableFormComponent.getSelectedRows();
// some actions with selectedRows
Запрет выбора некоторых строк в таблице
На вкладке Данные в поле Указать невыбираемые строки можно запретить выбор определенных строк в таблице:
Установка выбранных строк по умолчанию
На вкладке Данные в поле Указать выбираемые строки можно указать, какие строки должны быть выбраны по умолчанию:
Флаг «Разрешить ручное переопределение вычисляемого значения»/ «Allow Manual Override of Calculated Value»
На вкладке Данные выставленный флаг разрешает принудительно перезаписать пользователю поле, где уже введено вычисляемое значение.
См. подробно
Статические заголовки
Для включения статического заголовка необходимо в родительской форме проставить чекбокс Скрыть имя записи в модальном заголовке/ Hide record name in modal title. В данном случае произойдет скрытие имени ноды.
Так же, есть возможность задать свой локализованный статический заголовок. Для этого необходимо:
Создать в Локализация/Localization бандл с необходимой локализацией
Вставить ключ локализации в поле Укажите пользовательское статическое название поля для объединения с основным/ Enter custom static label for concat with basic. Если данный ключ не будет найден, то в заголовок добавится тот текст, что лежит в поле Укажите пользовательское статическое название поля для объединения с основным/ Enter custom static label for concat with basic
Импорт из файла
Появилась возможность импортировать в таблицу данные из файла (например, xslx). Для этого в настройки компонента добавлен раздел Импорт:
Поле URL для загрузки предназначено для указания url, куда будет отправляться POST-запрос с прикреплённым файлом (или несколькими файлами) для обработки. Обязательно к заполнению.
Поле Обработчик ответов предназначено для обработки результата ответа сервера после загрузки файла. Обязательно к заполнению. Принимает javascript-выражение, в котором необходимо присвоить переменной result строку (recordRef), массив строк (массив recordRef) или ошибку (result = new Error(„текст ошибки“)).
В javascript-выражении помимо стандартных объектов formio (data, instance, _, moment, и т.д.) доступна переменная response (или resp), которая содержит результат ответа сервера после загрузки файла.
После заполнения настроек у компонента должна появиться кнопка Импорт:
Примеры
Импортирование данных
Работа с файлами обычно делегируется бэкенду.
Создадим новый тип для импортирования данных excel-files-import.yml и форму excel-files-inport-form.json
Для отображения строк используем дочерний тип excel-files-import-line.yml
ecos-app архив со всеми артефактами, который можно загрузить целиком по адресу v2/journals?journalId=ecos-apps&viewMode=table&ws=admin$workspace
Далее необходимо добавить основной тип в меню, открыть журнал, нажать «Создать», добавить файлы для импорта и нажать «Создать». На бэкенде ловится событие создания, обрабатываются файлы и заполняются строки.
Примерный вид, того как это будет выглядеть:
Для произвольной логики на бэкенде в Citeck есть возможность создания дополнительных микросервисов. Демо микросервис, который можно посмотреть для примера - https://github.com/Citeck/ecos-demo-app
Изменение стиля строки
У каждой строки можно заполнять флаг «совпадения» и повесить на этот атрибут форматтер
Пример формы excel-files-inport-form.json
Добавление строк
Таблицы на формах - способ представления дочерних сущностей.
Добавлять новые строки на бэкенде можно, указав корректные атрибуты _parent (ссылка на родителя) и _parentAtt (ассоциация родителя для связи с дочерней сущностью).
recordsService.create("type@excel-files-import-line", ObjectData.create()
.set("name", "custom-name")
.set("validLine", true)
.set(RecordConstants.ATT_PARENT, "emodel/excel-files-import@0fd3353c-8a9f-47bc-b3f9-26ec92b1245c")
.set(RecordConstants.ATT_PARENT_ATT, "importedLines")
);